%% -*- mode: erlang -*-
%% ex: ft=erlang

%% @doc Allow anonymous users to connect, default is 'off'. !!NOTE!!
%% Enabling this completely disables authentication of the clients and
%% should only be used for testing/development purposes or in case
%% clients are authenticated by some other means.
{mapping, "allow_anonymous", "vmq_server.allow_anonymous", [
                                                               {default, off},
                                                               {datatype, flag}
                                                              ]}.

%% @doc Allow new client connections even when a VerneMQ cluster is inconsistent.
{mapping, "allow_register_during_netsplit", "vmq_server.allow_register_during_netsplit", [
                                                                                          {default, off},
                                                                                          {datatype, flag}
                                                                                         ]}.

%% @doc Allow message publishs even when a VerneMQ cluster is inconsistent.
{mapping, "allow_publish_during_netsplit", "vmq_server.allow_publish_during_netsplit", [
                                                                                        {default, off},
                                                                                        {datatype, flag}
                                                                                       ]}.

%% @doc Allow new subscriptions even when a VerneMQ cluster is inconsistent.
{mapping, "allow_subscribe_during_netsplit", "vmq_server.allow_subscribe_during_netsplit", [
                                                                                            {default, off},
                                                                                            {datatype, flag}
                                                                                           ]}.

%% @doc Allow clients to unsubscribe when a VerneMQ cluster is inconsistent.
{mapping, "allow_unsubscribe_during_netsplit", "vmq_server.allow_unsubscribe_during_netsplit", [
                                                                                                {default, off},
                                                                                                {datatype, flag}
                                                                                               ]}.

%% @doc Client registrations can be either happen in a coordinated or
%% uncoordinated fashion. Uncoordinated registrations are faster and
%% will cause other clients with the same client-id to be eventually
%% disconnected, while coordinated ensures that any other client with
%% the same client-id will be immediately disconnected.
{mapping, "coordinate_registrations", "vmq_server.coordinate_registrations",
 [{default, on},
  {datatype, flag}]}.

%% Retrain subscriber mode defines if subscribers on topics with retrained flag set should wait for 
%% a retrain server sync or process immmediatly.
{mapping, "subscriber_retain_mode", "vmq_server.subscriber_retain_mode", [
                                                               {default, immediate},
                                                               {datatype, atom},
                                                               hidden
                                                              ]}.

{translation, "vmq_server.subscriber_retain_mode",
 fun(Conf) ->
         case cuttlefish:conf_get("subscriber_retain_mode", Conf) of
             immediate -> immediate;
             syncwait -> syncwait;
             _ -> cuttlefish:invalid("subscriber_retain_mode must be either 'immediate' or 'syncwait'!")
         end
 end}.

%% @doc queue_type enables to change the default queue delivery behaviour from
%% 'fifo' to 'lifo'. In order to make this work the underlying message store
%% must deliver the messages in proper order.
{mapping, "queue_type", "vmq_server.queue_type", [
                                                  {default, fifo},
                                                  {datatype, atom},
                                                  hidden
                                                 ]}.

{translation, "vmq_server.queue_type",
 fun(Conf) ->
         case cuttlefish:conf_get("queue_type", Conf) of
             fifo -> fifo;
             lifo -> lifo;
             _ -> cuttlefish:invalid("queue_type must be either 'fifo' or 'lifo'!")
         end
 end}.

%% @doc Due to the eventual consistent nature of the subscriber store it is
%% possible that during queue migration messages still arrive on the old cluster
%% node. This parameter allows to compensate this by keeping the queue around
%% for some time after it was migrated to the other cluster node.
{mapping, "max_drain_time", "vmq_server.max_drain_time", [
                                                          {default, 500},
                                                          {datatype, integer},
                                                          hidden
                                                         ]}.

%% @doc Specifies the number of messages that are delviered to the remote
%% node per drain step. A large value will provide a faster migration of a queue,
%% but increases the waste of bandwidth in case the migration fails.
{mapping, "max_msgs_per_drain_step", "vmq_server.max_msgs_per_drain_step", [
                                                                            {default, 100},
                                                                            {datatype, integer},
                                                                            hidden
                                                                           ]}.

%% @doc Specifies the number of queue supervisors. The number of
%% queues per supervisor should never become too large as this can
%% lead to overload situations on massive disconnects of clients (as
%% each supervisor needs to handle all the disconnect messages of its
%% child queues). A reasonable max number of child queues per
%% supervisor is probably in the range of 2k-6k, but varies depending
%% on the hardware used.
{mapping, "queue_sup_sup_children", "vmq_server.queue_sup_sup_children", [
                                                                            {default, 50},
                                                                            {datatype, integer},
                                                                            hidden
                                                                           ]}.

%% @doc Secret to be used for crendentials obfuscation. Default is "random" which 
%% generates a random string. 
{mapping, "logging.obfuscation_secret", "vmq_server.logging", [
                                                            {datatype, [string]},
                                                            {default, "random"}
                                                           ]}.
%% @doc Client disconnect due to keepalive is by default a warning. In unstable networks
%% it might be "expected" behaviour to have a lot of those warnings. This allows to 
%% downgrade the warning to an info message.
{mapping, "logging.keepalive_as_warning", "vmq_server.logging", [
                                                            {datatype, flag},
                                                            {default, on}
                                                           ]}.

{translation, "vmq_server.logging",
 fun(Conf) ->
    [{keep_alive_as_warning, cuttlefish:conf_get("logging.keepalive_as_warning", Conf, true)},
     {obfuscation_secret, cuttlefish:conf_get("logging.obfuscation_secret", Conf, random)}]
 end}.

%% @doc Allows to select a new default reg_view.
%% A view is a pre-defined way to route messages. Multiple views can be
%% loaded and used, but one has to be selected as a default. The default routing is
%% vmq_reg_trie, i.e. routing via the built-in trie data structure.
{mapping, "default_reg_view", "vmq_server.default_reg_view", [
                                                              {default, vmq_reg_trie},
                                                              {datatype, atom},
                                                              hidden
                                                             ]}.
%% @doc the views that are started during startup
{mapping, "reg_views", "vmq_server.reg_views", [
                                                {default, "[vmq_reg_trie]"},
                                                {datatype, string},
                                                hidden
                                               ]}.

{translation, "vmq_server.reg_views",
 fun(Conf) ->
         S = cuttlefish:conf_get("reg_views", Conf),
         {ok, T, _} = erl_scan:string(S ++ "."),
         {ok, Term} = erl_parse:parse_term(T),
         Term
 end}.

%% @doc Set the time in seconds VerneMQ waits before a retry, in case a (QoS=1 or QoS=2) message
%% delivery gets no answer.
{mapping, "retry_interval", "vmq_server.retry_interval", [
                                                             {default, 20},
                                                             {commented, 20},
                                                             {datatype, integer}
                                                            ]}.

%% @doc Set the maximum size for client IDs. MQTT v3.1 specifies a
%% limit of 23 characters
{mapping, "max_client_id_size", "vmq_server.max_client_id_size", [
                                                               {default, 100},
                                                               {commented, 100},
                                                               {datatype, integer}
                                                              ]}.

%% @doc This option allows persistent clients ( = clean session set to
%% false) to be removed if they do not reconnect within 'persistent_client_expiration'.
%% This is a non-standard option. As far as the MQTT specification is concerned,
%% persistent clients persist forever.
%% The expiration period should be an integer followed by one of 'd', 'w', 'm', 'y' for
%% day, week, month, and year.
{mapping, "persistent_client_expiration", "vmq_server.persistent_client_expiration", [
                                                                                      {default, "never"},
                                                                                      {commented, "1w"},
                                                                                      {datatype, string}
                                                                                     ]}.

{translation, "vmq_server.persistent_client_expiration",
 fun(Conf) ->
         S = cuttlefish:conf_get("persistent_client_expiration", Conf),
         case S of
             "never" -> 0;
             _ ->
                 case vmq_schema:string_to_secs(S) of
                     error ->
                         cuttlefish:invalid(S ++ " must be an integer followed by one of 'h', 'd', 'w', 'm', 'y' for hour, day, week, month, and year, or the string 'never'");
                     Val -> Val
                 end
         end
 end}.

%% @doc The maximum delay for a last will message. This setting
%% applies only to MQTTv5 sessions and can be used to override the
%% value provided by the client.

%% The delay can be either 'client' which means the value specified by
%% the client is used, or an integer followed by one of 's', 'h' 'd',
%% 'w', 'm', 'y' for day, week, month, and year used to cap the value
%% provided by the client..
{mapping, "max_last_will_delay", "vmq_server.max_last_will_delay", [
                                                                    {default, "client"},
                                                                    {commented, "client"},
                                                                    {datatype, string}
                                                                   ]}.

{translation, "vmq_server.max_last_will_delay",
 fun(Conf) ->
         S = cuttlefish:conf_get("max_last_will_delay", Conf),
         case S of
             "client" ->
                 %% 2^32 max seconds in a Four Byte Integer
                 4294967296;
             _ ->
                 case vmq_schema:string_to_secs(S) of
                     error ->
                         cuttlefish:invalid(S ++ " must be an integer followed by one of 's', 'h', 'd', 'w', 'm', 'y' for second, minute, hour, day, week, month, and year");
                     Val -> Val
                 end
         end
 end}.


%% @doc The maximum number of QoS 1 or 2 messages that can be in the process of being
%% transmitted simultaneously. This includes messages currently going through handshakes
%% and messages that are being retried. Defaults to 20. Set to 0 for no maximum. If set
%% to 1, this will guarantee in-order delivery of messages.
%% Note: for MQTT v5, use receive_max_client/receive_max_broker to implement
%% similar behaviour.
{mapping, "max_inflight_messages", "vmq_server.max_inflight_messages", [
                                                                        {default, 20},
                                                                        {datatype, integer}
                                                                       ]}.

%% @doc The maximum number of messages to hold in the queue above
%% those messages that are currently in flight. Defaults to 1000. This affects
%% messages of any QoS. Set to -1 for no maximum (not recommended).
%% This option allows to control how a specific client session can deal
%% with message bursts. As a general rule of thumb set
%% this number a bit higher than the expected message rate a single consumer is
%% required to process. Note that setting this value to 0 will totally block
%% delivery from any queue.
{mapping, "max_online_messages", "vmq_server.max_online_messages", [
                                                    {default, 1000},
                                                    {datatype, integer}
                                                 ]}.

%% @doc The maximum number of QoS 1 or 2 messages to hold in the offline queue.
%% Defaults to 1000. Set to -1 for no maximum (not recommended). Set to 0
%% if no messages should be stored offline.
{mapping, "max_offline_messages", "vmq_server.max_offline_messages", [
                                                    {default, 1000},
                                                    {datatype, integer}
                                                 ]}.

%% @doc specify in case multiple sessions are allowed how the queue should
%% deliver the messages. In case of 'fanout' all the attached sessions
%% will receive the message, in case of 'balance' an attached session is
%% chosen randomly.
{mapping, "queue_deliver_mode", "vmq_server.queue_deliver_mode", [{default, fanout},
                                                                  {datatype, atom},
                                                                  hidden]}.

%% @doc Allows a session that changes from offline to online to override the maximum
%% online message count (max_online_messages). All offlines messages will be added
%% to the online queue.
{mapping, "override_max_online_messages", "vmq_server.override_max_online_messages", [{default, off},
                                                  {datatype, flag}
                                                  ]}.

%% @doc specify how the queue should process the messages,
%% either the 'fifo' or 'lifo' way.
{mapping, "queue_type", "vmq_server.queue_type", [{default, fifo},
                                                  {datatype, atom},
                                                  hidden]}.

%% @doc specifies the maximum incoming publish rate per session. Depending
%% on the underlying network buffers this rate isn't enforced.
%% defaults to 0, which means no rate limits apply
{mapping, "max_message_rate", "vmq_server.max_message_rate", [
                                                              {default, 0},
                                                              {datatype, integer},
                                                              hidden
                                                             ]}.

%% @doc This option sets the maximum MQTT size that VerneMQ will
%% allow.  Messages that exceed this size will not be accepted by
%% VerneMQ. The default value is 0, which means that all valid MQTT
%% messages are accepted. MQTT imposes a maximum payload size of
%% 268435455 bytes.
{mapping, "max_message_size", "vmq_server.max_message_size", [
                                                              {default, 0},
                                                              {datatype, integer}
                                                             ]}.

%% @doc If a message is published with a QoS lower than the QoS of the subscription it is
%% delivered to, VerneMQ can upgrade the outgoing QoS. This is a non-standard option.
{mapping, "upgrade_outgoing_qos", "vmq_server.upgrade_outgoing_qos", [
                                                                      {default, off},
                                                                      {datatype, flag}
                                                                     ]}.

%% @doc specifies how many size in bytes are buffered in case the remote node
%% is not available.
{mapping, "outgoing_clustering_buffer_size", "vmq_server.outgoing_clustering_buffer_size", [
                                                                                            {default, 10000},
                                                                                            {datatype, integer},
                                                                                            hidden
                                                                                           ]}.

%% @doc specifies the timeout for enqueuing something in a queue on a remote node.
{mapping, "remote_enqueue_timeout", "vmq_server.remote_enqueue_timeout", [
                                                                          {default, 5000},
                                                                          {datatype, [integer, {atom, infinity}]},
                                                                          hidden
                                                                         ]}.

%% @doc specifies the connect timeout.
{mapping, "mqtt_connect_timeout", "vmq_server.mqtt_connect_timeout", [
                                                            {default, 5000},
                                                            {datatype, integer},
                                                            hidden
                                                           ]}.


%% @doc specifies the modules to be enabled by the http(s) listeners. Overriding this setting is possible for specific listeners.
{mapping, "http_modules", "vmq_server.http_modules", [
                                                      {default, "[vmq_metrics_http,vmq_http_mgmt_api, vmq_status_http, vmq_health_http,
                                                                vmq_http_v2_api]"},
                                                      {datatype, string},
                                                      hidden
                                                     ]}.

{translation, "vmq_server.http_modules",
 fun(Conf) ->
         S = cuttlefish:conf_get("http_modules", Conf),
         {ok, T, _} = erl_scan:string(S ++ "."),
         {ok, Term} = erl_parse:parse_term(T),
         Term
 end}.

%% @doc specifies the minimal length of an API key (default: 0)
{mapping, "min_apikey_length", "vmq_server.min_apikey_length", [{datatype, integer}, {default, 0},
                                                                               hidden
                                                                                ]}.
%% @doc specifies the max duration of an API key before it expires (default: undefined)
{mapping, "max_apikey_expiry_days", "vmq_server.max_apikey_expiry_days", [{datatype, integer}, {default, undefined},
                                                                               hidden
                                                                                ]}.

%% @doc http_module.$module.auth.mode lets you select the authentication method for accessing the http_module.
%% You can set this option global, or an a listener level.
%%
%% - listener.http.$name.http_module.$module.auth.mode
%% - listener.https.$name.http_module.$module.auth.mode
%%
%% The default for vmq_http_mgmt_api, vmq_http_v2 and vmq_http_pub is "apikey", for all others it is noauth.
{mapping, "http_module.$name.auth.mode", "vmq_server.http_modules_auth", [{datatype, string}, {default, "noauth"},
                                                                               hidden
                                                                                ]}.
{mapping, "http_module.vmq_http_mgmt_api.auth.mode", "vmq_server.http_modules_auth", [{datatype, string}, {default, "apikey"},
                                                                               hidden
                                                                                ]}.
{mapping, "http_module.vmq_http_pub.auth.mode", "vmq_server.http_modules_auth", [{datatype, string}, {default, "apikey"},
                                                                               hidden
                                                                                ]}.
{mapping, "http_module.vmq_http_v2_api.auth.mode", "vmq_server.http_modules_auth", [{datatype, string}, {default, "apikey"},
                                                                               hidden
                                                                                ]}.
{mapping, "listener.http.$name.http_module.$module.auth.mode", "vmq_server.http_listener_modules_auth", [{datatype, string},
                                                                               hidden
                                                                                ]}.
{mapping, "listener.https.$name.http_module.$module.auth.mode", "vmq_server.http_listener_modules_auth", [{datatype, string},
                                                                               hidden
                                                                                ]}.
{translation,
  "vmq_server.http_modules_auth",
  fun(Conf) ->
     HTTPModules = cuttlefish_variable:filter_by_prefix("http_module",Conf),
     HTTPModulesAsAtom = lists:map(fun(Element) -> list_to_atom(lists:nth(2,element(1, Element))) end, HTTPModules),
     KnownHttpModules = [vmq_metrics_http,vmq_http_mgmt_api, vmq_status_http, vmq_health_http, vmq_http_v2_api, vmq_http_pub, vmq_web_ui],
     UniqueModules = lists:usort(HTTPModulesAsAtom ++ KnownHttpModules),
     Map = lists:map(fun(Atom) -> String = "http_module."++atom_to_list(Atom)++".auth.mode", #{Atom => cuttlefish:conf_get(String, Conf, "noauth")} end, UniqueModules),
     Ret = maps:from_list(lists:foldl(fun(Elem, Acc) -> maps:to_list(Elem) ++ Acc end, [], Map)),
	 Ret
	 end
}.

{translation,
  "vmq_server.http_listener_modules_auth",
  fun(Conf) ->
     Candidates = cuttlefish_variable:filter_by_prefix("listener.http.",Conf) ++ cuttlefish_variable:filter_by_prefix("listener.https.",Conf),
	 HTTPModuleListers = lists:filter(fun(Elem) -> case element(1,Elem) of X when length(X)>5 -> lists:nth(4,X) == "http_module"; _ -> false end end, Candidates),
     MapListenerModule = lists:map(fun(Elem) -> Elem1 = element(1, Elem), {list_to_atom(lists:nth(2,Elem1)), list_to_atom(lists:nth(3,Elem1)), list_to_atom(lists:nth(5,Elem1))} end, HTTPModuleListers),
     MapWithValue = lists:map(fun(AtomTuple) -> String = "listener."++atom_to_list(element(1,AtomTuple))++"."++atom_to_list(element(2,AtomTuple))++".http_module."++atom_to_list(element(3,AtomTuple))++".auth.mode", #{AtomTuple => cuttlefish:conf_get(String, Conf)} end, MapListenerModule),
     Ret = maps:from_list(lists:foldl(fun(Elem, Acc) -> maps:to_list(Elem) ++ Acc end, [], MapWithValue)),
     Ret
	 end
}.




%% @doc listener.tcp.buffer_sizes is an list of three integers
%% (sndbuf,recbuf,buffer) specifying respectively the kernel TCP send
%% buffer, the kernel TCP receive buffer and the user-level buffer
%% size in the erlang driver.
%%
%% It is recommended to have val(user-level buffer) >= val(receive
%% buffer) to avoid performance issues because of unnecessary copying.
%%
%% If not set, the operating system defaults are used.
%%
%% This option can be set on the protocol level by:
%%
%%     - listener.tcp.buffer_sizes
%%     - listener.ssl.buffer_sizes
%%
%% or on the listener level by:
%%
%%     - listener.tcp.my_tcp_listener.buffer_sizes
%%     - listener.ssl.my_ssl_listener.buffer_sizes
{mapping, "listener.tcp.buffer_sizes", "vmq_server.listeners",
 [{commented, "4096,16384,32768"},
  {datatype, string},
  {validators, ["buffer_size_validator"]}
 ]}.

{mapping, "listener.tcp.$name.buffer_sizes", "vmq_server.listeners",
 [{datatype, string},
  hidden,
  {validators, ["buffer_size_validator"]}
 ]}.

{mapping, "listener.ssl.buffer_sizes", "vmq_server.listeners",
 [{datatype, string},
  hidden,
  {validators, ["buffer_size_validator"]}
 ]}.

{mapping, "listener.ssl.$name.buffer_sizes", "vmq_server.listeners",
 [{datatype, string},
  hidden,
  {validators, ["buffer_size_validator"]}
 ]}.

{mapping, "listener.vmq.$name.buffer_sizes", "vmq_server.listeners",
 [{datatype, string},
  hidden,
  {validators, ["buffer_size_validator"]}
 ]}.

 %% @doc Set the watermark levels for the `vmq_cluster_mon` listener
 %% That is, the listener receiving the MQTT messages from other nodes.
{mapping, "listener.vmq.$name.high_watermark", "vmq_server.listeners", [
                                                                  {default, 8192},
                                                                  {datatype, integer},
                                                                  hidden
                                                                ]}.
{mapping, "listener.vmq.$name.low_watermark", "vmq_server.listeners", [
                                                                  {default, 4096},
                                                                  {datatype, integer},
                                                                  hidden
                                                                ]}.
{mapping, "listener.vmq.$name.high_msgq_watermark", "vmq_server.listeners", [
                                                                  {default, 8192},
                                                                  {datatype, integer},
                                                                  hidden
                                                                ]}.
{mapping, "listener.vmq.$name.low_msgq_watermark", "vmq_server.listeners", [
                                                                  {default, 4096},
                                                                  {datatype, integer},
                                                                  hidden
                                                                ]}.

{validator, "buffer_size_validator", "value must be three comma-separated, positive integers",
 fun(Val) when is_list(Val) ->
         case vmq_schema:parse_list_to_term(Val) of
             {ok, [A,B,C]} when is_integer(A), is_integer(B), is_integer(C),
                                A >= 0, B >= 0, C >= 0 ->
                 true;
             _ ->
                 false
         end;
    (Val) ->
         false
 end}.

%% @doc listener.max_connection_lifetime is an integer defining the maximum lifetime
%% of MQTT connection in seconds. This option can be overridden on the protocol level by:
%%
%%     - listener.tcp.max_connection_lifetime
%%     - listener.ssl.max_connection_lifetime
%%     - listener.ws.max_connection_lifetime
%%     - listener.wss.max_connection_lifetime
%%
%% or on the listener level by:
%%
%%     - listener.tcp.my_tcp_listener.max_connection_lifetime
%%     - listener.ssl.my_ssl_listener.max_connection_lifetime
%%     - listener.ws.my_ws_listener.max_connection_lifetime
%%     - listener.wss.my_wss_listener.
%%
%% This is an implementation of MQTT security proposal:
%% "Servers may close the Network Connection of Clients and require them to re-authenticate with new credentials."
{mapping, "listener.max_connection_lifetime", "vmq_server.listeners", [
                                                                  {default, 0},
                                                                  {datatype, integer}
                                                                 ]}.

{mapping, "listener.tcp.max_connection_lifetime", "vmq_server.listeners", [
                                                                      {datatype, [integer]},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.tcp.$name.max_connection_lifetime", "vmq_server.listeners", [
                                                                            {datatype, [integer]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ssl.max_connection_lifetime", "vmq_server.listeners", [
                                                                      {datatype, [integer]},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.ssl.$name.max_connection_lifetime", "vmq_server.listeners", [
                                                                            {datatype, [integer]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ws.max_connection_lifetime", "vmq_server.listeners", [
                                                                            {datatype, [integer]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ws.$name.max_connection_lifetime", "vmq_server.listeners", [
                                                                                  {datatype, [integer]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.wss.max_connection_lifetime", "vmq_server.listeners", [
                                                                            {datatype, [integer]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.wss.$name.max_connection_lifetime", "vmq_server.listeners", [
                                                                                  {datatype, [integer]},
                                                                                  hidden
                                                                                 ]}.

%% @doc listener.max_connections is an integer or 'infinity' defining
%% the maximum number of concurrent connections. This option can be overridden
%% on the protocol level by:
%%
%%     - listener.tcp.max_connections
%%     - listener.ssl.max_connections
%%     - listener.ws.max_connections
%%     - listener.wss.max_connections
%%
%% or on the listener level by:
%%
%%     - listener.tcp.my_tcp_listener.max_connections
%%     - listener.ssl.my_ssl_listener.max_connections
%%     - listener.ws.my_ws_listener.max_connections
%%     - listener.wss.my_wss_listener.max_connections
{mapping, "listener.max_connections", "vmq_server.listeners", [
                                                                  {default, {{max_connections}} },
                                                                  {datatype, [integer, {atom, infinity}]}
                                                                 ]}.

{mapping, "listener.tcp.max_connections", "vmq_server.listeners", [
                                                                      {default, -1},
                                                                      {datatype, [integer, {atom, infinity}]},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.tcp.$name.max_connections", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ssl.max_connections", "vmq_server.listeners", [
                                                                      {default, -1},
                                                                      {datatype, [integer, {atom, infinity}]},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.ssl.$name.max_connections", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ws.max_connections", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ws.$name.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.wss.max_connections", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.wss.$name.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmq.max_connections", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.
{mapping, "listener.vmq.$name.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmqs.max_connections", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.
{mapping, "listener.vmqs.$name.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.http.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.http.$name.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.https.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.https.$name.max_connections", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
%% @doc Set the maximum frame in bytes that a WebSocket connection is allowed to
%% send. If the client tries to send more in one frame, the server will disconnect it.

{mapping, "max_ws_frame_size", "vmq_server.max_ws_frame_size", [
                                                                  {default, 256*1024*1024 },
                                                                  {datatype, [integer, {atom, infinity}]}
                                                                 ]}.

%% @doc Set the nr of acceptors waiting to concurrently accept new connections.
%% This can be specified either on the protocol level:
%%
%%     - listener.tcp.nr_of_acceptors
%%     - listener.ssl.nr_of_acceptors
%%     - listener.ws.nr_of_acceptors
%%     - listener.wss.nr_of_acceptors
%%
%% or on the listener level:
%%
%%     - listener.tcp.my_tcp_listener.nr_of_acceptors
%%     - listener.ssl.my_ssl_listener.nr_of_acceptors
%%     - listener.ws.my_ws_listener.nr_of_acceptors
%%     - listener.wss.my_wss_listener.nr_of_acceptors
{mapping, "listener.nr_of_acceptors", "vmq_server.listeners", [
                                                                  {default, {{ max_nr_of_acceptors}} },
                                                                  {datatype, integer}
                                                                 ]}.

{mapping, "listener.tcp.nr_of_acceptors", "vmq_server.listeners", [
                                                                      {default, -1},
                                                                      {datatype, integer},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.tcp.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, integer},
                                                                            {include_default, "default"},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ssl.nr_of_acceptors", "vmq_server.listeners", [
                                                                      {default, -1},
                                                                      {datatype, integer},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.ssl.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, integer},
                                                                            {include_default, "default"},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ws.nr_of_acceptors", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, integer},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.ws.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, integer},
                                                                                  {include_default, "default"},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.wss.nr_of_acceptors", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, integer},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.wss.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, integer},
                                                                                  {include_default, "default"},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmq.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmq.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  {include_default, "default"},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmqs.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmqs.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  {include_default, "default"},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.http.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.http.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  {include_default, "default"},
                                                                                  hidden
                                                                         ]}.
{mapping, "listener.https.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.https.$name.nr_of_acceptors", "vmq_server.listeners", [
                                                                                  {default, 10},
                                                                                  {datatype, integer},
                                                                                  {include_default, "default"},
                                                                                  hidden
                                                                          ]}.

%% @doc Set the TLS handshake timeout (in milliseconds). This represents the maximum
%% time that can be spent completing the TLS handshake for the protocol.
%%
%% It can be useful to set this to a higher value when clients are running on
%% constrained devices (e.g. microcontrollers) which can take more than 5 seconds
%% (the default value) to complete the TLS handshake.
%%
%% This can be specified either on the protocol level:
%%
%%     - listener.ssl.tls_handshake_timeout
%%     - listener.wss.tls_handshake_timeout
%%     - listener.vmqs.tls_handshake_timeout
%%     - listener.https.tls_handshake_timeout
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.tls_handshake_timeout
%%     - listener.wss.my_wss_listener.tls_handshake_timeout
%%     - listener.vmqs.my_vmqs_listener.tls_handshake_timeout
%%     - listener.https.my_https_listener.tls_handshake_timeout
{mapping, "listener.ssl.tls_handshake_timeout", "vmq_server.listeners", [
                                                                      {default, -1},
                                                                      {datatype, [integer, {atom, infinity}]},
                                                                      hidden
                                                                     ]}.

{mapping, "listener.ssl.$name.tls_handshake_timeout", "vmq_server.listeners", [
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.wss.tls_handshake_timeout", "vmq_server.listeners", [
                                                                            {default, -1},
                                                                            {datatype, [integer, {atom, infinity}]},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.wss.$name.tls_handshake_timeout", "vmq_server.listeners", [
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.

{mapping, "listener.vmqs.tls_handshake_timeout", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.vmqs.$name.tls_handshake_timeout", "vmq_server.listeners", [
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.

{mapping, "listener.https.tls_handshake_timeout", "vmq_server.listeners", [
                                                                                  {default, -1},
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                                 ]}.

{mapping, "listener.https.$name.tls_handshake_timeout", "vmq_server.listeners", [
                                                                                  {datatype, [integer, {atom, infinity}]},
                                                                                  hidden
                                                                          ]}.

%% @doc listener.tcp.<name> is an IP address and TCP port that
%% the broker will bind to. You can define multiple listeners e.g:
%% - listener.tcp.default = 127.0.0.1:1883
%% - listener.tcp.internal = 127.0.0.1:10883
%% - listener.tcp.my_other_listener = 127.0.0.1:10884
%% This also works for SSL listeners and WebSocket handlers:
%% - listener.ssl.default = 127.0.0.1:8883
%% - listener.ws.default = 127.0.0.1:800
%% - listener.wss.default = 127.0.0.1:880
{mapping, "listener.tcp.$name", "vmq_server.listeners", [
                                                                {commented, { "{{mqtt_default_ip}}", {{mqtt_default_port}} }},
                                                                {datatype, [ip, domain_socket]}
                                                                ]}.

{mapping, "listener.ws.$name", "vmq_server.listeners", [
                                                                  {commented, { "{{mqtt_default_ws_ip}}", {{mqtt_default_ws_port}} }},
                                                                  {datatype, ip},
                                                                  hidden
                                                                 ]}.

{mapping, "listener.wss.$name", "vmq_server.listeners", [
                                                                  {commented, { "{{mqtt_default_ws_ip}}", {{mqtt_default_ws_port}} }},
                                                                  {datatype, ip},
                                                                  hidden
                                                                 ]}.

{mapping, "listener.ssl.$name", "vmq_server.listeners", [
                                                            {commented, { "{{mqtts_default_ip}}", {{mqtts_default_port}} }},
                                                            {datatype, ip}
                                                           ]}.

%% @doc listener.tcp.proxy_protocol specifies if the listener accepts
%% connections opened by a proxy server that supports the PROXY protocol. This
%% enables to retrieve peer information such as source IP/Port but also for the
%% PROXY Version 2 protocol TLS client certificate details if the proxy was used
%% to terminate TLS (and also supports the PROXY protocol).
{mapping, "listener.tcp.proxy_protocol", "vmq_server.listeners", [
                                                                  {default, off},
                                                                  {datatype, flag},
                                                                  hidden
                                                                 ]}.
{mapping, "listener.tcp.$name.proxy_protocol", "vmq_server.listeners", [
                                                                        {datatype, flag},
                                                                        hidden
                                                                       ]}.

{mapping, "listener.ws.proxy_protocol", "vmq_server.listeners", [
                                                                  {default, off},
                                                                  {datatype, flag},
                                                                  hidden
                                                                 ]}.
{mapping, "listener.ws.$name.proxy_protocol", "vmq_server.listeners", [
                                                                        {datatype, flag},
                                                                        hidden
                                                                       ]}.
{mapping, "listener.http.proxy_protocol", "vmq_server.listeners", [
                                                                  {default, off},
                                                                  {datatype, flag},
                                                                  hidden
                                                                 ]}.
{mapping, "listener.http.$name.proxy_protocol", "vmq_server.listeners", [
                                                                        {datatype, flag},
                                                                        hidden
                                                                       ]}.
%% @doc listener.ws.xff_support specifies if the listener accepts
%% connections opened by a proxy server that supports the  X-Forwarded-For header.
%% This enables to retrieve peer information such as source IP/Port.
{mapping, "listener.ws.$name.proxy_xff_support", "vmq_server.listeners", [
                                                                        {datatype, flag},
                                                                        hidden
                                                                       ]}.
{mapping, "listener.ws.proxy_xff_support", "vmq_server.listeners", [
                                                                  {default, off},
                                                                  {datatype, flag},
                                                                  hidden
                                                                 ]}.
%% @doc listener.ws.proxy_xff_trusted_intermediate specifies the
%% list of proxies accepted within the X-Forwarded-For list as last proxy. The other
%% proxies in the chain are not checked.
{mapping, "listener.ws.$name.proxy_xff_trusted_intermediate", "vmq_server.listeners", [
                                                                        {datatype, string},
                                                                        hidden
                                                                       ]}.
{mapping, "listener.ws.proxy_xff_trusted_intermediate", "vmq_server.listeners", [
                                                                  {default, ""},
                                                                  {datatype, string},
                                                                  hidden
                                                                 ]}.

{mapping, "listener.ws.$name.proxy_xff_use_cn_as_username", "vmq_server.listeners", [
                                                                  {default, off},
                                                                  {datatype, flag},
                                                                  hidden
                                                                 ]}.

{mapping, "listener.ws.$name.proxy_xff_cn_header", "vmq_server.listeners", [
                                                                  {default, "x-ssl-client-cn"},
                                                                  {datatype, string},
                                                                  hidden
                                                                 ]}.


%% @doc If 'listener.tcp.proxy_protocol' is enabled, you may enable
%% 'listener.tcp.proxy_protocol_use_cn_as_username' to use the CN
%% (sni_hostname) passed via the PROXY protocol instead of the MQTT
%% username. The option can be specified either for all tcp or
%% websocket listeners:
%%
%%     - listener.tcp.proxy_protocol_use_cn_as_username
%%     - listener.ws.proxy_protocol_use_cn_as_username
%%
%% or for a specific listener:
%%
%%     - listener.tcp.my_tcp_listener.use_cn_as_username
%%     - listener.ws.my_ws_listener.use_cn_as_username
{mapping, "listener.tcp.proxy_protocol_use_cn_as_username", "vmq_server.listeners", [
                                                                            {default, on},
                                                                            {datatype, flag},
                                                                            hidden
                                                                           ]}.

{mapping, "listener.tcp.$name.proxy_protocol_use_cn_as_username", "vmq_server.listeners", [
                                                                                  {datatype, flag},
                                                                                  hidden
                                                                                 ]}.

{mapping, "listener.ws.proxy_protocol_use_cn_as_username", "vmq_server.listeners", [
                                                                           {default, on},
                                                                           {datatype, flag},
                                                                           hidden
                                                                          ]}.

{mapping, "listener.ws.$name.proxy_protocol_use_cn_as_username", "vmq_server.listeners", [
                                                                                 {datatype, flag},
                                                                                 hidden
                                                                                ]}.
{mapping, "listener.http.proxy_protocol_use_cn_as_username", "vmq_server.listeners", [
                                                                             {default, on},
                                                                             {datatype, flag},
                                                                             hidden
                                                                            ]}.

{mapping, "listener.http.$name.proxy_protocol_use_cn_as_username", "vmq_server.listeners", [
                                                                                   {datatype, flag},
                                                                                   hidden
                                                                                  ]}.

%% @doc 'listener.tcp.my_listener.allow_anonymous_override' configures whether
%% this listener is allowed to override the global allow_anonymous setting.
%% The setting has one single purpose: to give a listener the capability to switch off
%% all authentication plugins. (that is override a global allow_anonymous=off with a per-listener allow_anonymous=on).
%% Specifically, it can allow TLS listeners to disable internal authentication (using only client certificates as
%% authentication) while keeping all the other MQTT listeners safe.
%% global | listener | Result for listener:  (on = anonymous access allowed)
%% on	  | on	     | on
%% off    | on	     | on
%% off    | off      | off
%% on     | off      | on
%% Both values are simply OR'ed together. Please note that this does not allow you to globally allow anonymous access, and
%% then selectively switch off single listeners!
%%
%%     - listener.tcp.my_listener.allow_anonymous_override
%%     - listener.ssl.my_listener.allow_anonymous_override
%%
%% Allowed values are 'on' or 'off'. The default value for an unconfigured listener will be 'off'.
{mapping, "listener.tcp.$name.allow_anonymous_override", "vmq_server.listeners",
 [
  {default, off},
  {datatype, flag}
 ]}.

 {mapping, "listener.ssl.$name.allow_anonymous_override", "vmq_server.listeners",
 [
  {default, off},
  {datatype, flag}
 ]}.

%% @doc 'listener.tcp.allowed_protocol_versions' configures which
%% protocol versions are allowed for an MQTT listener. The allowed
%% protocol versions can be specified the tcp, websocket or ssl level:
%%
%%     - listener.tcp.allowed_protocol_versions
%%     - listener.ws.allowed_protocol_versions
%%     - listener.wss.allowed_protocol_versions
%%     - listener.ssl.allowed_protocol_versions
%%
%% or for a specific listener:
%%
%%     - listener.tcp.my_tcp_listener.allowed_protocol_versions
%%     - listener.ws.my_ws_listener.allowed_protocol_versions
%%     - listener.wss.my_ws_listener.allowed_protocol_versions
%%     - listener.ssl.my_ws_listener.allowed_protocol_versions
%%
%% Allowed values are 3 (MQTT 3.1), 4 (MQTT 3.1.1), 5 (MQTT 5.0), 131
%% (MQTT 3.1 bridge), 132 (MQTT 3.1.1 bridge).
{mapping, "listener.tcp.allowed_protocol_versions", "vmq_server.listeners",
 [
  {default, "3,4,5,131"},
  {datatype, string},
  {commented, "3,4,5"}
 ]}.

{mapping, "listener.tcp.$name.allowed_protocol_versions", "vmq_server.listeners",
 [
  {datatype, string},
  hidden
 ]}.

{mapping, "listener.ws.allowed_protocol_versions", "vmq_server.listeners",
 [
  {default, "3,4,5,131"},
  {datatype, string},
  hidden
 ]}.

{mapping, "listener.ws.$name.allowed_protocol_versions", "vmq_server.listeners",
 [
  {datatype, string},
  hidden
 ]}.

{mapping, "listener.wss.allowed_protocol_versions", "vmq_server.listeners",
 [
  {default, "3,4,5,131"},
  {datatype, string},
  hidden
 ]}.

{mapping, "listener.wss.$name.allowed_protocol_versions", "vmq_server.listeners",
 [
  {datatype, string},
  hidden
 ]}.

{mapping, "listener.ssl.allowed_protocol_versions", "vmq_server.listeners",
 [
  {default, "3,4,5,131"},
  {datatype, string},
  hidden
 ]}.

{mapping, "listener.ssl.$name.allowed_protocol_versions", "vmq_server.listeners",
 [
  {datatype, string},
  hidden
 ]}.

%% @doc listener.vmq.clustering is the IP address and TCP port that
%% the broker will bind to accept connections from other cluster
%% nodes e.g:
%% - listener.vmq.clustering = 0.0.0.0:18883
%% This also works for SSL listeners:
%% - listener.vmqs.clustering = 0.0.0.0:18884
{mapping, "listener.vmq.$name", "vmq_server.listeners", [
                                                           {default, { "{{cluster_default_ip}}", {{cluster_default_port}} }},
                                                           {datatype, ip},
                                                           {include_default, "clustering"}
                                                          ]}.
{mapping, "listener.vmqs.$name", "vmq_server.listeners", [
                                                           {default, { "{{cluster_ssl_default_ip}}", {{cluster_ssl_default_port}} }},
                                                           {datatype, ip},
                                                           hidden
                                                          ]}.

%% @doc listener.http.default is the IP address and TCP port that
%% the broker will bind to accept HTTP connections
%% - listener.http.default = 0.0.0.0:8888
%% This also works for SSL listeners:
%% - listener.https.default= 0.0.0.0:8889
{mapping, "listener.http.$name", "vmq_server.listeners", [
                                                          {default, { "{{http_default_ip}}", {{http_default_port}} }},
                                                          {datatype, ip},
                                                          {include_default, "default"}
                                                         ]}.
{mapping, "listener.http.$name.config_mod", "vmq_server.listeners", [
                                                                     {default, vmq_http_config},
                                                                     {datatype, atom},
                                                                     hidden
                                                                    ]}.

{mapping, "listener.http.$name.config_fun", "vmq_server.listeners", [
                                                                     {default, config},
                                                                     {datatype, atom},
                                                                     hidden
                                                                    ]}.
%% @doc specifies the modules to be enabled by the http(s) listener
{mapping, "listener.http.$name.http_modules", "vmq_server.listeners", [
                                                      {default, "[]"},
                                                      {datatype, string},
                                                      hidden
                                                     ]}.


{mapping, "listener.https.$name", "vmq_server.listeners", [
                                                          {default, { "{{https_default_ip}}", {{https_default_port}} }},
                                                          {datatype, ip},
                                                          hidden
                                                         ]}.
{mapping, "listener.https.$name.config_mod", "vmq_server.listeners", [
                                                                     {default, vmq_http_config},
                                                                     {datatype, atom},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.https.$name.config_fun", "vmq_server.listeners", [
                                                                     {default, config},
                                                                     {datatype, atom},
                                                                     hidden
                                                                    ]}.
%% @doc specifies the modules to be enabled by the http(s) listener
{mapping, "listener.https.$name.http_modules", "vmq_server.listeners", [
                                                      {default, "[]"},
                                                      {datatype, string},
                                                      hidden
                                                     ]}.

%% @doc The maximum length of the HTTP request in bytes (Cowboy's max_request_line_length)
{mapping, "listener.http.$name.max_request_line_length", "vmq_server.listeners", [
                                                                     {default, 8000},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.https.$name.max_request_line_length", "vmq_server.listeners", [
                                                                     {default, 8000},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.ws.$name.max_request_line_length", "vmq_server.listeners", [
                                                                     {default, 8000},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.wss.$name.max_request_line_length", "vmq_server.listeners", [
                                                                     {default, 8000},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.

%% @doc The maximum length of the HTTP header in bytes (Cowboy's max_header_value_length)
{mapping, "listener.http.$name.max_header_value_length", "vmq_server.listeners", [
                                                                     {default, 4096},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.https.$name.max_header_value_length", "vmq_server.listeners", [
                                                                     {default, 4096},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.ws.$name.max_header_value_length", "vmq_server.listeners", [
                                                                     {default, 4096},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.wss.$name.max_header_value_length", "vmq_server.listeners", [
                                                                     {default, 4096},
                                                                     {datatype, integer},
                                                                     hidden
                                                                    ]}.

%% @doc Set the mountpoint on the protocol level or on the listener level
%%
%%     - listener.tcp.mountpoint
%%     - listener.ssl.mountpoint
%%     - listener.ws.mountpoint
%%     - listener.wss.mountpoint
%%
%% listener level:
%%
%%     - listener.tcp.my_tcp_listener.mountpoint
%%     - listener.ssl.my_ssl_listener.mountpoint
%%     - listener.ws.my_ws_listener.mountpoint
%%     - listener.wss.my_wss_listener.mountpoint
{mapping, "listener.mountpoint", "vmq_server.listeners", [{default, "off"},
                                                          {datatype, string},
                                                          hidden
                                                         ]}.
{mapping, "listener.tcp.mountpoint", "vmq_server.listeners", [
                                                              {datatype, string},
                                                              hidden
                                                             ]}.

{mapping, "listener.tcp.$name.mountpoint", "vmq_server.listeners", [
                                                                    {datatype, string},
                                                                    hidden
                                                                   ]}.

{mapping, "listener.ws.mountpoint", "vmq_server.listeners", [
                                                             {datatype, string},
                                                             hidden
                                                            ]}.

{mapping, "listener.ws.$name.mountpoint", "vmq_server.listeners", [
                                                                   {datatype, string},
                                                                   hidden
                                                                  ]}.

{mapping, "listener.wss.mountpoint", "vmq_server.listeners", [
                                                              {datatype, string},
                                                              hidden
                                                             ]}.

{mapping, "listener.wss.$name.mountpoint", "vmq_server.listeners", [
                                                                    {datatype, string},
                                                                    hidden
                                                                   ]}.

{mapping, "listener.ssl.mountpoint", "vmq_server.listeners", [
                                                              {datatype, string},
                                                              hidden
                                                             ]}.

{mapping, "listener.ssl.$name.mountpoint", "vmq_server.listeners", [
                                                                    {datatype, string},
                                                                    hidden
                                                                ]}.
{mapping, "listener.vmq.mountpoint", "vmq_server.listeners", [
                                                              {datatype, string},
                                                              hidden
                                                             ]}.

{mapping, "listener.vmq.$name.mountpoint", "vmq_server.listeners", [
                                                                    {datatype, string},
                                                                    hidden
                                                                   ]}.
{mapping, "listener.vmqs.mountpoint", "vmq_server.listeners", [
                                                               {datatype, string},
                                                               hidden
                                                              ]}.

{mapping, "listener.vmqs.$name.mountpoint", "vmq_server.listeners", [
                                                                     {datatype, string},
                                                                     hidden
                                                                    ]}.

%% @doc The cafile is used to define the path to a file containing
%% the PEM encoded CA certificates that are trusted. Set the cafile
%% on the protocol level or on the listener level:
%%
%%     - listener.ssl.cafile
%%     - listener.wss.cafile
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.cafile
%%     - listener.wss.my_wss_listener.cafile
{mapping, "listener.ssl.cafile", "vmq_server.listeners", [
                                                          {default, ""},
                                                          {datatype, file},
                                                          {commented, "{{platform_etc_dir}}/cacerts.pem"},
                                                          {validators, ["file-exists", "file-is-readable"]}
                                                         ]}.

{mapping, "listener.ssl.$name.cafile", "vmq_server.listeners", [
                                                                {datatype, file},
                                                                {validators, ["file-exists", "file-is-readable"]},
                                                                hidden
                                                               ]}.
{mapping, "listener.wss.cafile", "vmq_server.listeners", [
                                                          {default, ""},
                                                          {datatype, file},
                                                          {validators, ["file-exists", "file-is-readable"]},
                                                          hidden
                                                         ]}.
{mapping, "listener.wss.$name.cafile", "vmq_server.listeners", [
                                                                {datatype, file},
                                                                {validators, ["file-exists", "file-is-readable"]},
                                                                hidden
                                                               ]}.
{mapping, "listener.vmqs.cafile", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, file},
                                                           {validators, ["file-exists", "file-is-readable"]},
                                                           hidden
                                                          ]}.
{mapping, "listener.vmqs.$name.cafile", "vmq_server.listeners", [
                                                                {datatype, file},
                                                                {validators, ["file-exists", "file-is-readable"]},
                                                                hidden
                                                               ]}.
{mapping, "listener.https.cafile", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, file},
                                                            {validators, ["file-exists", "file-is-readable"]},
                                                            {commented, "{{platform_etc_dir}}/cacerts.pem"}
                                                           ]}.

{mapping, "listener.https.$name.cafile", "vmq_server.listeners", [
                                                                {datatype, file},
                                                                {validators, ["file-exists", "file-is-readable"]},
                                                                hidden
                                                               ]}.

%% @doc When dealing with an intermediate CA, it might be required to
%% increase the peer verification depth to have a client certificate
%% correctly validated. The default value (1) means that only certificates
%% signed by the root CA will be accepted, whereas an higher value allows
%% for a deeper verification chain. Please refer to http://erlang.org/doc/man/ssl.html
%% for further documentation. Set the certificate
%% verification depth on the protocol level or on the listener level:
%%
%%     - listener.ssl.depth
%%     - listener.wss.depth
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.depth
%%     - listener.wss.my_wss_listener.depth
{mapping, "listener.ssl.depth", "vmq_server.listeners", [
                                                          {default, 1},
                                                          {datatype, integer},
                                                          hidden
                                                         ]}.

{mapping, "listener.ssl.$name.depth", "vmq_server.listeners", [
                                                                {datatype, integer},
                                                                hidden
                                                               ]}.
{mapping, "listener.wss.depth", "vmq_server.listeners", [
                                                         {default, 1},
                                                         {datatype, integer},
                                                         hidden
                                                        ]}.
{mapping, "listener.wss.$name.depth", "vmq_server.listeners", [
                                                                {datatype, integer},
                                                                hidden
                                                               ]}.
{mapping, "listener.vmqs.depth", "vmq_server.listeners", [
                                                          {default, 1},
                                                          {datatype, integer},
                                                          hidden
                                                         ]}.
{mapping, "listener.vmqs.$name.depth", "vmq_server.listeners", [
                                                                {datatype, integer},
                                                                hidden
                                                               ]}.
{mapping, "listener.https.depth", "vmq_server.listeners", [
                                                          {default, 1},
                                                          {datatype, integer},
                                                          hidden
                                                         ]}.
{mapping, "listener.https.$name.depth", "vmq_server.listeners", [
                                                                {datatype, integer},
                                                                hidden
                                                               ]}.

%% @doc Set the path to the PEM encoded server certificate
%% on the protocol level or on the listener level:
%%
%%     - listener.ssl.certfile
%%     - listener.wss.certfile
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.certfile
%%     - listener.wss.my_wss_listener.certfile
{mapping, "listener.ssl.certfile", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, file},
                                                            {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                            {commented, "{{platform_etc_dir}}/cert.pem"}
                                                           ]}.
{mapping, "listener.ssl.$name.certfile", "vmq_server.listeners", [
                                                                  {datatype, file},
                                                                  {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                  hidden
                                                                 ]}.
{mapping, "listener.wss.certfile", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, file},
                                                            {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                            hidden
                                                           ]}.
{mapping, "listener.wss.$name.certfile", "vmq_server.listeners", [
                                                                  {datatype, file},
                                                                  {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                  hidden
                                                                 ]}.
{mapping, "listener.vmqs.certfile", "vmq_server.listeners", [
                                                             {default, ""},
                                                             {datatype, file},
                                                             {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                             hidden
                                                            ]}.
{mapping, "listener.vmqs.$name.certfile", "vmq_server.listeners", [
                                                                   {datatype, file},
                                                                   {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                   hidden
                                                                  ]}.
{mapping, "listener.https.certfile", "vmq_server.listeners", [
                                                              {default, ""},
                                                              {datatype, file},
                                                              {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                              {commented, "{{platform_etc_dir}}/cert.pem"}
                                                             ]}.
{mapping, "listener.https.$name.certfile", "vmq_server.listeners", [
                                                                    {datatype, file},
                                                                    {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                    hidden
                                                                 ]}.
%% @doc Set the path to the PEM encoded key file on the protocol
%% level or on the listener level:
%%
%%     - listener.ssl.keyfile
%%     - listener.wss.keyfile
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.keyfile
%%     - listener.wss.my_wss_listener.keyfile
{mapping, "listener.ssl.keyfile", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, file},
                                                           {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                           {commented, "{{platform_etc_dir}}/key.pem"}
                                                          ]}.
{mapping, "listener.ssl.$name.keyfile", "vmq_server.listeners", [
                                                                 {datatype, file},
                                                                 {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                 hidden
                                                                ]}.
{mapping, "listener.wss.keyfile", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, file},
                                                           {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                           hidden
                                                          ]}.
{mapping, "listener.wss.$name.keyfile", "vmq_server.listeners", [
                                                                 {datatype, file},
                                                                 {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                 hidden
                                                                ]}.
{mapping, "listener.vmqs.keyfile", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, file},
                                                            {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                            {commented, "{{platform_etc_dir}}/key.pem"}
                                                           ]}.
{mapping, "listener.vmqs.$name.keyfile", "vmq_server.listeners", [
                                                                  {datatype, file},
                                                                  {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                  hidden
                                                                ]}.
{mapping, "listener.https.keyfile", "vmq_server.listeners", [
                                                             {default, ""},
                                                             {datatype, file},
                                                             {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                             {commented, "{{platform_etc_dir}}/key.pem"}
                                                            ]}.
{mapping, "listener.https.$name.keyfile", "vmq_server.listeners", [
                                                                   {datatype, file},
                                                                   {validators, ["file-exists", "file-is-readable", "file-is-pem"]},
                                                                   hidden
                                                                  ]}.
%% @doc Set the path to the PEM encoded key file on the protocol
%% level or on the listener level:
%%
%%     - listener.ssl.keypasswd
%%     - listener.wss.keypasswd
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.keypasswd
%%     - listener.wss.my_wss_listener.keypasswd
{mapping, "listener.ssl.keypasswd", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, string},
                                                           hidden
                                                          ]}.
{mapping, "listener.ssl.$name.keypasswd", "vmq_server.listeners", [
                                                             {datatype, string},
                                                             hidden
                                                                ]}.
{mapping, "listener.wss.keypasswd", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, string},
                                                           hidden
                                                          ]}.
{mapping, "listener.wss.$name.keypasswd", "vmq_server.listeners", [
                                                             {datatype, string},
                                                              hidden
                                                              ]}.
{mapping, "listener.vmqs.keypasswd", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, string},
                                                             hidden
                                                      ]}.
{mapping, "listener.vmqs.$name.keypasswd", "vmq_server.listeners", [
                                                                  {datatype, string},
                                                                   hidden
                                                                ]}.
{mapping, "listener.https.keypasswd", "vmq_server.listeners", [
                                                             {default, ""},
                                                             {datatype, string},
                                                              hidden
                                                            ]}.
{mapping, "listener.https.$name.keypasswd", "vmq_server.listeners", [
                                                                   {datatype, string},
                                                                   hidden
                                                                  ]}.
%% @doc Set the list of allowed ciphers (each separated with a colon,
%% e.g. "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"),
%% on the protocol level or on the listener level. Reasonable defaults
%% are used if nothing is specified:
%%
%%     - listener.ssl.ciphers
%%     - listener.wss.ciphers
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.ciphers
%%     - listener.wss.my_wss_listener.ciphers
{mapping, "listener.ssl.ciphers", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, string},
                                                           {commented, ""}
                                                          ]}.
{mapping, "listener.ssl.$name.ciphers", "vmq_server.listeners", [
                                                                 {datatype, string},
                                                                 hidden
                                                                ]}.
{mapping, "listener.wss.ciphers", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, string},
                                                           hidden
                                                          ]}.
{mapping, "listener.wss.$name.ciphers", "vmq_server.listeners", [
                                                                 {datatype, string},
                                                                 hidden
                                                                ]}.
{mapping, "listener.vmqs.ciphers", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, string},
                                                            {commented, ""}
                                                           ]}.
{mapping, "listener.vmqs.$name.ciphers", "vmq_server.listeners", [
                                                                 {datatype, string},
                                                                 hidden
                                                                ]}.
{mapping, "listener.https.ciphers", "vmq_server.listeners", [
                                                              {default, ""},
                                                              {datatype, string},
                                                              {commented, ""}
                                                             ]}.
{mapping, "listener.https.$name.ciphers", "vmq_server.listeners", [
                                                                 {datatype, string},
                                                                 hidden
                                                                ]}.
%% @doc Set the list of allowed elliptical curves (each separated with a colon,
%% e.g. "[sect571k1,secp521r1,brainpoolP512r1]"), on the protocol level or on the listener level.
%% All known curves are used if nothing is specified.
%%
%%     - listener.ssl.eccs
%%     - listener.wss.eccs
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.eccs
%%     - listener.wss.my_wss_listener.eccs
{mapping, "listener.ssl.eccs", "vmq_server.listeners", [
                                                        {default, ""},
                                                        {datatype, string},
                                                        {commented, "[brainpoolP384r1, secp384r1, sect283k1]"}
                                                       ]}.
{mapping, "listener.ssl.$name.eccs", "vmq_server.listeners", [
                                                              {default, ""},
                                                              {datatype, string},
                                                              hidden
                                                             ]}.
{mapping, "listener.wss.eccs", "vmq_server.listeners", [
                                                        {default, ""},
                                                        {datatype, string},
                                                        hidden
                                                       ]}.
{mapping, "listener.wss.$name.eccs", "vmq_server.listeners", [
                                                              {default, ""},
                                                              {datatype, string},
                                                              hidden
                                                             ]}.
{mapping, "listener.vmqs.eccs", "vmq_server.listeners", [
                                                         {default, ""},
                                                         {datatype, string},
                                                         {commented, "[brainpoolP384r1, secp384r1, sect283k1]"}
                                                        ]}.
{mapping, "listener.vmqs.$name.eccs", "vmq_server.listeners", [
                                                               {default, ""},
                                                               {datatype, string},
                                                               hidden
                                                              ]}.
{mapping, "listener.https.eccs", "vmq_server.listeners", [
                                                          {default, ""},
                                                          {datatype, string},
                                                          {commented, "[brainpoolP384r1, secp384r1, sect283k1]"}
                                                        ]}.
{mapping, "listener.https.$name.eccs", "vmq_server.listeners", [
                                                                {default, ""},
                                                                {datatype, string},
                                                                hidden
                                                               ]}.
%% @doc If you have 'listener.ssl.require_certificate' set to true,
%% you can create a certificate revocation list file to revoke access
%% to particular client certificates. If you have done this, use crlfile
%% to point to the PEM encoded revocation file. This can be done on the
%% protocol level or on the listener level.
%%
%%     - listener.ssl.crlfile
%%     - listener.wss.crlfile
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.crlfile
%%     - listener.wss.my_wss_listener.crlfile
{mapping, "listener.ssl.crlfile", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, file},
                                                           {validators, ["file-exists", "file-is-readable"]},
                                                           {commented, ""}
                                                          ]}.
{mapping, "listener.ssl.$name.crlfile", "vmq_server.listeners", [
                                                                 {datatype, file},
                                                                 {validators, ["file-exists", "file-is-readable"]},
                                                                 hidden
                                                                ]}.
{mapping, "listener.wss.crlfile", "vmq_server.listeners", [
                                                           {default, ""},
                                                           {datatype, file},
                                                           {validators, ["file-exists", "file-is-readable"]},
                                                           hidden
                                                          ]}.
{mapping, "listener.wss.$name.crlfile", "vmq_server.listeners", [
                                                                 {datatype, file},
                                                                 {validators, ["file-exists", "file-is-readable"]},
                                                                 hidden
                                                                ]}.
{mapping, "listener.vmqs.crlfile", "vmq_server.listeners", [
                                                            {default, ""},
                                                            {datatype, file},
                                                            {validators, ["file-exists", "file-is-readable"]},
                                                            hidden
                                                           ]}.
{mapping, "listener.vmqs.$name.crlfile", "vmq_server.listeners", [
                                                                 {datatype, file},
                                                                  {validators, ["file-exists", "file-is-readable"]},
                                                                 hidden
                                                                ]}.
{mapping, "listener.https.crlfile", "vmq_server.listeners", [
                                                             {default, ""},
                                                             {datatype, file},
                                                             {validators, ["file-exists", "file-is-readable"]},
                                                             hidden
                                                            ]}.
{mapping, "listener.https.$name.crlfile", "vmq_server.listeners", [
                                                                   {datatype, file},
                                                                   {validators, ["file-exists", "file-is-readable"]},
                                                                   hidden
                                                                  ]}.
%% @doc Enable this option if you want to use SSL client certificates
%% to authenticate your clients. This can be done on the protocol level
%% or on the listener level.
%%
%%     - listener.ssl.require_certificate
%%     - listener.wss.require_certificate
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.require_certificate
%%     - listener.wss.my_wss_listener.require_certificate
{mapping, "listener.ssl.require_certificate", "vmq_server.listeners", [
                                                                       {default, off},
                                                                       {datatype, flag},
                                                                       {commented, off}
                                                                      ]}.
{mapping, "listener.ssl.$name.require_certificate", "vmq_server.listeners", [
                                                                             {datatype, flag},
                                                                             hidden
                                                                            ]}.
{mapping, "listener.wss.require_certificate", "vmq_server.listeners", [
                                                                       {default, off},
                                                                       {datatype, flag},
                                                                       hidden
                                                                      ]}.
{mapping, "listener.wss.$name.require_certificate", "vmq_server.listeners", [
                                                                             {datatype, flag},
                                                                             hidden
                                                                            ]}.
{mapping, "listener.vmqs.require_certificate", "vmq_server.listeners", [
                                                                        {default, off},
                                                                        {datatype, flag},
                                                                        {commented, off}
                                                                       ]}.
{mapping, "listener.vmqs.$name.require_certificate", "vmq_server.listeners", [
                                                                             {datatype, flag},
                                                                             hidden
                                                                            ]}.
{mapping, "listener.https.require_certificate", "vmq_server.listeners", [
                                                                         {default, off},
                                                                         {datatype, flag},
                                                                         {commented, off}
                                                                        ]}.
{mapping, "listener.https.$name.require_certificate", "vmq_server.listeners", [
                                                                             {datatype, flag},
                                                                             hidden
                                                                            ]}.
%% @doc Configure one ore more TLS protocol version(s) (tlsv1, tlsv1.1, tlsv1.2 or tlsv1.3) 
%% to be used for either all configured SSL listeners or for a specific listener:
%%
%%     - listener.ssl.tls_version
%%     - listener.wss.tls_version
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.tls_version
%%     - listener.wss.my_wss_listener.tls_version
%% Example for multi-version listener:
%%     - listener.ssl.my_ssl_listener.tls_version = tlsv1.2,tlsv1.3
%% (add versions comma-separated, no space)
{mapping, "listener.ssl.tls_version", "vmq_server.listeners", [
                                                               {default, "tlsv1.2"},
                                                               {datatype, string},
                                                               {commented, "tlsv1.2"}
                                                              ]}.
{mapping, "listener.ssl.$name.tls_version", "vmq_server.listeners", [
                                                                     {datatype, string},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.wss.tls_version", "vmq_server.listeners", [
                                                               {default, "tlsv1.2"},
                                                               {datatype, string},
                                                               hidden
                                                              ]}.
{mapping, "listener.wss.$name.tls_version", "vmq_server.listeners", [
                                                                     {datatype, string},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.vmqs.tls_version", "vmq_server.listeners", [
                                                                {default, 'tlsv1.2'},
                                                                {datatype, atom},
                                                                {commented, 'tlsv1.2'}
                                                               ]}.
{mapping, "listener.vmqs.$name.tls_version", "vmq_server.listeners", [
                                                                     {datatype, atom},
                                                                     hidden
                                                                    ]}.
{mapping, "listener.https.tls_version", "vmq_server.listeners", [
                                                                 {default, "tlsv1.2"},
                                                                 {datatype, string},
                                                                 {commented, "tlsv1.2"}
                                                                ]}.
{mapping, "listener.https.$name.tls_version", "vmq_server.listeners", [
                                                                     {datatype, string},
                                                                     hidden
                                                                    ]}.
%% @doc If 'listener.ssl.require_certificate' is enabled, you may enable
%% 'listener.ssl.use_identity_as_username' to use the CN value from the client
%% certificate as a username. If enabled other authentication plugins are not
%% considered. The option can be specified either for all SSL listeners or for
%% a specific listener:
%%
%%     - listener.ssl.use_identity_as_username
%%     - listener.wss.use_identity_as_username
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.use_identity_as_username
%%     - listener.wss.my_wss_listener.use_identity_as_username
{mapping, "listener.ssl.use_identity_as_username", "vmq_server.listeners", [
                                                                            {default, off},
                                                                            {datatype, flag},
                                                                            {commented, off}
                                                                           ]}.
{mapping, "listener.ssl.$name.use_identity_as_username", "vmq_server.listeners", [
                                                                                  {datatype, flag},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.wss.use_identity_as_username", "vmq_server.listeners", [
                                                                            {default, off},
                                                                            {datatype, flag},
                                                                            hidden
                                                                           ]}.
{mapping, "listener.wss.$name.use_identity_as_username", "vmq_server.listeners", [
                                                                                  {datatype, flag},
                                                                                  hidden
                                                                                 ]}.

%% @doc If 'listener.ssl.forward_connection_opts' is enabled, VerneMQ will
%% forward the full client certificate to the authentication plugin (in the
%% auth_on_register hooks).
%% Configure on protocol level (for all listeners):
%%
%%     - listener.ssl.forward_connection_opts
%%     - listener.wss.forward_connection_opts
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.forward_connection_opts
%%     - listener.wss.my_wss_listener.forward_connection_opts
{mapping, "listener.ssl.forward_connection_opts", "vmq_server.listeners", [
                                                                            {default, off},
                                                                            {datatype, flag},
                                                                            {commented, off}
                                                                           ]}.
{mapping, "listener.ssl.$name.forward_connection_opts", "vmq_server.listeners", [
                                                                                  {datatype, flag},
                                                                                  hidden
                                                                                 ]}.
{mapping, "listener.wss.forward_connection_opts", "vmq_server.listeners", [
                                                                            {default, off},
                                                                            {datatype, flag},
                                                                            hidden
                                                                           ]}.
{mapping, "listener.wss.$name.forward_connection_opts", "vmq_server.listeners", [
                                                                                  {datatype, flag},
                                                                                  hidden
                                                                                 ]}.                                       

%% @doc If listener.ssl.pskfile is enabled VerneMQ supports TLS connection based on
%% pre-shared keys (PSK).
%%
%% The option can be specified either for all SSL listeners or for
%% a specific listener.
%%
%%     - listener.ssl.psk_support
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.psk_support
{mapping, "listener.ssl.psk_support", "vmq_server.listeners", [
                                                               {default, off},
                                                               {datatype, flag},
                                                               {commented, off}
                                                              ]}.
{mapping, "listener.ssl.$name.psk_support", "vmq_server.listeners", [
                                                                     {datatype, flag},
                                                                      hidden
                                                                    ]}.
%% @doc The PSK hint sent by the server to the client.
%%
%% The option can be specified either for all SSL listeners or for
%% a specific listener.
%%
%%     - listener.ssl.psk_identity_hint
%%
%% or on the listener level:
%%
%%     - listener.ssl.my_ssl_listener.psk_identity_hint
{mapping, "listener.ssl.psk_identity_hint", "vmq_server.listeners", [
                                                               {default, "VMQ_PSK"},
                                                               {datatype, string},
                                                               {commented, "VMQ_PSK"}
                                                              ]}.
{mapping, "listener.ssl.$name.psk_identity_hint", "vmq_server.listeners", [
                                                                     {datatype, string},
                                                                      hidden
                                                                    ]}.


%% @doc If PSK support is enabled, the pre-shared keys must be provided as key value pairs
%% seperated by a seperator (by default ":"), e.g.
%%
%% mypskidentity:mypskkey
%%
%% The key is a string (not hex-encoded). The psk file is used for all listerners.
{mapping, "listener.ssl.pskfile", "vmq_server.listeners", [
                                                           {default, "{{platform_etc_dir}}/vmq.psk"},
                                                           {datatype, file}
                                                          ]}.
%% @doc The pre-shared keys and the psk identity are separated by a separator.
%% By default, a colon is used.
{mapping, "listener.ssl.pskfile_separator", "vmq_server.listeners", [
                                                               {default, ":"},
                                                               {datatype, string},
                                                               {commented, ":"},
                                                               {validators, ["separator_validator"]}
                                                              ]}.

{validator, "separator_validator", "separator must be  a 1 character string",
 fun(String) ->
         string:length(String) == 1
 end}.


{translation, "vmq_server.listeners",
 fun(Conf) ->
         vmq_schema:translate_listeners(Conf)
 end
}.

%% @doc The integer number of milli-seconds between certificate
%% revocation list refreshes. A value of 0 disables the automatic
%% refresh completely.
{mapping, "crl_refresh_interval", "vmq_server.crl_refresh_interval", [
                                                                      {default, 60000},
                                                                      {datatype, integer},
                                                                      {validators, ["non-neg-integer"]},
                                                                      hidden
                                                                     ]}.

{validator, "non-neg-integer", "must be a non-negative integer",
 fun(Integer) ->
         Integer >= 0
 end}.


%% @doc Enable the $SYSTree Reporter.
{mapping, "systree_enabled", "vmq_server.systree_enabled", [
                                                        {default, on},
                                                        {datatype, flag}
                                                       ]}.
%% @doc The integer number of milliseconds between updates of the $SYS subscription hierarchy,
%% which provides status information about the broker. If unset, defaults to 20 seconds.
%% Set to 0 to disable publishing the $SYS hierarchy completely.
{mapping, "systree_interval", "vmq_server.systree_interval", [
                                                       {default, 20000},
                                                       {datatype, integer}
                                                      ]}.
{mapping, "systree_mountpoint", "vmq_server.systree_mountpoint", [
                                                       {default, ""},
                                                       {datatype, string},
                                                       hidden
                                                      ]}.
{mapping, "systree_qos", "vmq_server.systree_qos", [
                                                       {default, 0},
                                                       {datatype, integer},
                                                       hidden
                                                      ]}.
{mapping, "systree_retain", "vmq_server.systree_retain", [
                                                       {default, off},
                                                       {datatype, flag},
                                                       hidden
                                                      ]}.
{mapping, "systree_reg_view", "vmq_server.systree_reg_view", [
                                                       {default, vmq_reg_trie},
                                                       {datatype, atom},
                                                       hidden
                                                      ]}.

%% @doc Prometheus namespace prefix 
{mapping, "prometheus_namespace", "vmq_server.prometheus_namespace", [
                                                        {default, "vernemq_"},
                                                        {datatype, string}
                                                       ]}.

{translation, "vmq_server.prometheus_namespace",
 fun(Conf) ->
     S = cuttlefish:conf_get("prometheus_namespace", Conf),
     case S of
         "\"\"" -> <<>>;
            S   -> S
     end
 end}.


%% @doc Enable the Graphite Reporter. Ensure to also configure a
%% proper graphite.host
{mapping, "graphite_enabled", "vmq_server.graphite_enabled", [
                                                        {default, off},
                                                        {datatype, flag}
                                                       ]}.

%% @doc the graphite server host name
{mapping, "graphite_host", "vmq_server.graphite_host", [
                                                        {default, "localhost"},
                                                        {datatype, string}
                                                       ]}.

%% @doc the tcp port of the graphite server
{mapping, "graphite_port", "vmq_server.graphite_port", [
                                                        {default, 2003},
                                                        {datatype, integer}
                                                       ]}.

%% @doc the interval we push metrics to the graphite server in ms
{mapping, "graphite_interval", "vmq_server.graphite_interval", [{default, 20000},
                                                                  {datatype, integer}
                                                                 ]}.

%% @doc set connect timeout
{mapping, "graphite_connect_timeout", "vmq_server.graphite_connect_timeout", [
                                                                              {default, 5000},
                                                                              {datatype, integer},
                                                                              hidden
                                                                             ]}.
%% @doc set connect timeout
{mapping, "graphite_reconnect_timeout", "vmq_server.graphite_reconnect_timeout", [
                                                                              {default, 15000},
                                                                              {datatype, integer},
                                                                              hidden
                                                                             ]}.

%% @doc set the prefix that is applied to all metrics reported to graphite
{mapping, "graphite_prefix", "vmq_server.graphite_prefix", [
                                                            {commented, "my-prefix"},
                                                            {default, ""},
                                                            {datatype, string}
                                                           ]}.

%% @doc the graphite server api key, e.g. used by hostedgraphite.com
{mapping, "graphite_api_key", "vmq_server.graphite_api_key", [
                                                              {commented, "My-Api-Key"},
                                                              {default, ""},
                                                              {datatype, string}
                                                             ]}.

%% @doc generate extra metrics from metrics with labels.
{mapping, "graphite_include_labels", "vmq_server.graphite_include_labels", [
                                                                            {default, off},
                                                                            {datatype, flag},
                                                                            hidden
                                                                           ]}.

{mapping, "plumtree.directory", "plumtree.plumtree_data_dir", [
                                             {default, "{{platform_data_dir}}/meta"},
                                             {datatype, directory},
                                             hidden
                                            ]}.

{mapping, "plumtree.outstanding_limit", "plumtree.outstanding_limit", [
                                                                       {default, 250000},
                                                                       {datatype, integer},
                                                                       hidden
                                                                      ]}.

{mapping, "plumtree.drop_i_have_threshold", "plumtree.drop_i_have_threshold", [
                                                                               {default, 1000000},
                                                                               {datatype, integer},
                                                                               hidden
                                                                              ]}.

%% the setup utility will call hooks to create the default directories,
%% however the setup defaults e.g. data.<nodename> are not matching with our
%% defaults, so we need to override them.
{mapping, "setup.log_dir", "setup.log_dir", [
                                             {default, "{{platform_log_dir}}/"},
                                             {datatype, directory},
                                             hidden
                                            ]}.
{mapping, "setup.data_dir", "setup.data_dir", [
                                             {default, "{{platform_data_dir}}/"},
                                             {datatype, directory},
                                             hidden
                                            ]}.


{mapping, "tcp_listen_options", "vmq_server.tcp_listen_options", [
                                                                  {default, "[{nodelay, true}, {linger, {true, 0}}, {send_timeout, 30000}, {send_timeout_close, true}]"},
                                                                  {datatype, string},
                                                                  hidden
                                                                 ]}.
{translation, "vmq_server.tcp_listen_options",
 fun(Conf) ->
         S = cuttlefish:conf_get("tcp_listen_options", Conf),
         {ok, T, _} = erl_scan:string(S ++ "."),
         {ok, Term} = erl_parse:parse_term(T),
         Term
 end}.


%% @doc Set the TCP connection options for the outgoing part
%% of the vmq transport logic (inter-node traffic). The options
%% will be given to gen_tcp:connect/4 or ssl:connect/4. Note that
%% "binary" and "{active, true}" are hard-coded options.
{mapping, "outgoing_connect_options", "vmq_server.outgoing_connect_options", [
                                                                  {default, "[{keepalive, true}, {send_timeout, 0}]"},
                                                                  {datatype, string},
                                                                  hidden
                                                                 ]}.
{translation, "vmq_server.outgoing_connect_options",
 fun(Conf) ->
         S = cuttlefish:conf_get("outgoing_connect_options", Conf),
         {ok, T, _} = erl_scan:string(S ++ "."),
         {ok, Term} = erl_parse:parse_term(T),
         Term
 end}.

%% @doc Distribution policy for shared subscriptions. Default is
%% 'prefer_local' which will ensure that local subscribers will be
%% used if any are available. 'local_only' will select a random local
%% subscriber if any are available. 'random' will randomly choose
%% between all available subscribers.
{mapping, "shared_subscription_policy", "vmq_server.shared_subscription_policy", [
                                                                                  {default, prefer_local},
                                                                                  {datatype, atom}
                                                                                 ]}.

%% @doc What action should be taken if enqueuing a shared subscriber
%% message to a subscriber on a remote node fails due to a timeout. If
%% this happens it is not certain if the remote subscriber has
%% received the message or not. If the remote subscriber has not
%% received the message and the action is `ignore`, the message will
%% be lost. If the remote subscriber did receive the message and the
%% action is `requeue` and a subscriber successfully accepts the
%% message, the message will be delivered to both shared subscribers.
{mapping, "shared_subscription_timeout_action",
 "vmq_server.shared_subscription_timeout_action", [
                                                   {default, ignore},
                                                   {datatype, {enum, [ignore, requeue]}},
                                                   hidden
                                                  ]}.

%% @doc Suppress the Last Will and Testament message if an existing
%% session already exists for the connecting client.
{mapping, "suppress_lwt_on_session_takeover",
 "vmq_server.suppress_lwt_on_session_takeover", [
                                                 {default, off},
                                                 {datatype, flag},
                                                 hidden
                                                ]}.

%% @doc plugins.<plugin> enables/disables a plugin.
%%
%% Plugin specific settings are set via the plugin itself, i.e., to
%% set the 'file' setting for the myplugin plugin, add a line like:
%%
%%
%% myplugin.file = /path/to/file
{mapping, "plugins.$name", "vmq_server.user_plugins", [
                                                       {datatype, flag},
                                                       {commented, on}
                                                      ]}.

%% @doc plugins.<name>.path defines the location of the plugin
%% associated with <name>. This is needed for plugins that are not
%% shipped with VerneMQ.
{mapping, "plugins.$name.path", "vmq_server.user_plugins", [
                                                            {datatype, directory},
                                                            {commented, "/path/to/myplugin"},
                                                            {include_default, "mypluginname"}
                                                          ]}.

%% @doc plugins.<name>.priority defines the load order of the
%% plugins. Plugins are loaded by priority. If no priority is given
%% the load order is undefined. Prioritized plugins will always be
%% loaded before plugins with no defined priority.
{mapping, "plugins.$name.priority", "vmq_server.user_plugins", [
                                                                {datatype, integer},
                                                                {commented, "5"},
                                                                {include_default, "mypluginname"}
                                                               ]}.



%% @doc File based authentication plugin.
{mapping, "plugins.vmq_passwd", "vmq_server.user_plugins", [
                                                            {datatype, flag},
                                                            {default, on}
                                                           ]}.

%% @doc File based authorization plugin.
{mapping, "plugins.vmq_acl", "vmq_server.user_plugins", [
                                                         {datatype, flag},
                                                         {default, on}
                                                        ]}.

%% @doc Lua based plugins.
{mapping, "plugins.vmq_diversity", "vmq_server.user_plugins", [
                                                               {datatype, flag},
                                                               {default, off}
                                                              ]}.

%% @doc Webhook based plugins.
{mapping, "plugins.vmq_webhooks", "vmq_server.user_plugins", [
                                                               {datatype, flag},
                                                               {default, off}
                                                             ]}.
%% @doc The VerneMQ bridge plugin.
{mapping, "plugins.vmq_bridge", "vmq_server.user_plugins", [
                                                            {datatype, flag},
                                                            {default, off}
                                                           ]}.

{translation,
 "vmq_server.user_plugins",
 fun(Conf) ->
         PluginNames =
             proplists:get_all_values(
               "$name",
               cuttlefish_variable:fuzzy_matches(["plugins", "$name"], Conf)),
         EnabledPlugins =
             lists:filter(fun(Name) ->
                                  cuttlefish:conf_get("plugins." ++ Name, Conf, false)
                          end,
                          PluginNames),
         Plugins =
             [ {cuttlefish:conf_get("plugins." ++ Name ++ ".priority", Conf, Name),
                #{path => cuttlefish:conf_get("plugins." ++ Name ++ ".path", Conf, undefined),
                  name => erlang:list_to_atom(Name)}}
               || Name <- EnabledPlugins ],
         lists:keysort(1, Plugins)
 end}.

%% @doc Specifies the maximum incoming topic alias range on the broker for each
%% client. A value of 0 means topic aliases are not allowed.
{mapping, "topic_alias_max_client", "vmq_server.topic_alias_max_client", [
                                                                          {default, 0},
                                                                          {datatype, integer},
                                                                          hidden
                                                                         ]}.

%% @doc Specifies the maximum outgoing topic alias range on the broker for each
%% client. A value of 0 means topic aliases are not allowed.
{mapping, "topic_alias_max_broker", "vmq_server.topic_alias_max_broker", [
                                                                          {default, 0},
                                                                          {datatype, integer},
                                                                          hidden
                                                                         ]}.

%% @doc Limits the maximum topic depth
{mapping, "topic_max_depth", "vmq_server.topic_max_depth", [
                                                            {default, 10},
                                                            {datatype, integer}
                                                           ]}.

%% @doc Specifies the maximum number of unacknowledged MQTTv5 Publish packets
%% VerneMQ is allowed to send to a client. Each client can set their own
%% receive maximum (via the `receive_max`property of the CONNECT frame).
%% VerneMQ ensures that a client provided maximum never exceeds the
%% `receive_max_client` value.
{mapping, "receive_max_client", "vmq_server.receive_max_client", [
                                                                  {default, 65535},
                                                                  {datatype, integer},
                                                                  hidden
                                                                 ]}.

%% @doc Specifies the maximum number of unacknowledged MQTTv5 Publish packets
%% VerneMQ is allowed to receive from a client. VerneMQ advertises this value
%% in the `receive_max` property of the CONNACK frame. A client is disconnected
%% when exceeding this value.
{mapping, "receive_max_broker", "vmq_server.receive_max_broker", [
                                                                  {default, 65535},
                                                                  {datatype, integer},
                                                                  hidden
                                                                 ]}.

%% @doc Specifies the metadata plugin that is used for storing and replicating
%% VerneMQ metadata objects such as MQTT subscriptions and retained messages.
%%
%% For new cluster deployments, the recommendation is to use 'vmq_swc' from the
%% beginning. Note that the 2 protocols are not compatible, so clusters can't be
%% mixed.
{mapping, "metadata_plugin", "vmq_server.metadata_impl", [{default, {{ metadata_plugin }} },
                                                          {datatype, {enum, [vmq_plumtree, vmq_swc]}}
                                                         ]}.

{mapping, "message_store_plugin", "vmq_server.message_store_impl", [{default, vmq_generic_msg_store},
                                                                    {datatype, atom},
                                                                    hidden
                                                                   ]}.

{validator, "file-exists", "file does not exist",
 fun("") ->
         %% "" is used as the default value in most places, we should
         %% not error out because of that.
         true;
    (Name) -> vmq_schema_util:file_exists(Name)
 end}.
{validator, "file-is-readable", "file is not readable, check permissions",
 fun("") ->
         %% "" is used as the default value in most places, we should
         %% not error out because of that.
         true;
    (Name) -> vmq_schema_util:file_is_readable(Name)
 end}.
{validator, "file-is-pem", "file is not PEM-encoded with one or more entries",
 fun("") ->
         %% "" is used as the default value in most places, we should
         %% not error out because of that.
         true;
    (Name) -> vmq_schema_util:file_is_pem_content(Name)
 end}.

%% @doc Disconnect v3.1 clients in case they are not authorized to publish. This breaks the MQTT 3.1 specification
%% and is intended for old unpatchable MQTT 3.1 client devices.
{mapping, "disconnect_on_unauthorized_publish_v3", "vmq_server.disconnect_on_unauthorized_publish_v3", [{default, off},
                                                                                                        {datatype, flag},
                                                                                                        hidden
                                                                                                       ]}.

%% @doc Retain Cache expiry cleanup in seconds
%% Cleanup expired retained messages
%% (set by the publisher using message-expiry-interval). 
%% Setting to 0 disables the feature. This feature is only helpful
%% when you never overwrite or consume retained messages; usually
%% expired retained messages are cleaned up at the next delivery attempt.
{mapping, "expire_retain_cache", "vmq_server.expire_retain_cache", [
                                                             {default, 60},
                                                             {commented, 60},
                                                             {datatype, integer}
                                                            ]}.
